﻿using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Text;
using System.Configuration;

using BizElements.BusinessLayer;

namespace BizElements.Web
{
    /// <summary>
    /// <see cref="DataGrid"/> template which displays and edits the value of a bound field in a <see cref="BoundTextBox"/> control.
    /// </summary>
    public class BoundTextBoxTemplate : BoundTemplateBase
    {
        #region Constructors.

        /// <summary>
        /// Initializes a new instance of the <see cref="BoundTextBoxTemplate"/> class.
        /// </summary>
        public BoundTextBoxTemplate()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BoundTextBoxTemplate"/> class.
        /// </summary>
        /// <param name="field"><see cref="IBindableField"/> that contains a reference and meta-data for a bound business class property.</param>
        /// <param name="formatter">The <see cref="IMessageFormatter"/> object used to format bound values.</param>
        public BoundTextBoxTemplate(IBindableField field, IMessageFormatter formatter)
            : base(field, formatter)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BoundTextBoxTemplate"/> class.
        /// </summary>
        /// <param name="field"><see cref="IBindableField"/> that contains a reference and meta-data for a bound business class property.</param>
        /// <param name="formatter">The <see cref="IMessageFormatter"/> object used to format bound values.</param>
        /// <param name="skinID">The skin to apply to the controls generated by this template.</param>
        public BoundTextBoxTemplate(IBindableField field, IMessageFormatter formatter, string skinID)
            : base(field, formatter, skinID)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BoundTextBoxTemplate"/> class.
        /// </summary>
        /// <param name="field"><see cref="IBindableField"/> that contains a reference and meta-data for a bound business class property.</param>
        /// <param name="formatter">The <see cref="IMessageFormatter"/> object used to format bound values.</param>
        /// <param name="width">The width of the textbox used in the template.</param>
        /// <param name="cssClass">CSS Class name applied to textbox created by the template.</param>
        /// <param name="readOnlyCss">CSS Class name applied to controls created by the template when in read-only mode.</param>
        public BoundTextBoxTemplate(IBindableField field, IMessageFormatter formatter, int width, string cssClass, string readOnlyCss)
            : base(field, formatter, width, cssClass, readOnlyCss)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BoundTextBoxTemplate"/> class.
        /// </summary>
        /// <param name="field"><see cref="IBindableField"/> that contains a reference and meta-data for a bound business class property.</param>
        /// <param name="formatter">The <see cref="IMessageFormatter"/> object used to format bound values.</param>
        /// <param name="width">The width of the textbox used in the template.</param>
        /// <param name="cssClass">CSS Class name applied to textbox created by the template.</param>
        /// <param name="readOnlyCss">CSS Class name applied to controls created by the template when in read-only mode.</param>
        /// <param name="maxLength">The maximum number of characters allowed in the textbox created by the template.</param>
        /// <param name="allowedChars">The list of characters a user is allowed to enter in the textbox created by the template.</param>
        public BoundTextBoxTemplate(IBindableField field, IMessageFormatter formatter, int width, string cssClass, string readOnlyCss, int maxLength, string allowedChars)
            : base(field, formatter, width, cssClass, readOnlyCss)
        {
            this.MaxLength = maxLength;
            this.AllowedChars = allowedChars;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="BoundTextBoxTemplate"/> class.
        /// </summary>
        /// <param name="width">The width of the textbox used in the template.</param>
        public BoundTextBoxTemplate(Unit width)
        {
            this.Width = width;
        }

        #endregion

        #region Properties.

        /// <summary>
        /// Gets or sets the maximum number of characters allowed in the textbox created by the template.
        /// </summary>
        public int MaxLength { get; set; }

        /// <summary>
        /// Gets or sets the list of characters a user is allowed to enter in the textbox created by the template.
        /// </summary>
        public string AllowedChars { get; set; }

        /// <summary>
        /// Gets or sets the behavior mode (single-line, multiline, or password) of the textbox created by the template.
        /// </summary>
        public TextBoxMode TextMode { get; set; }

        /// <summary>
        /// Gets or sets the number of rows displayed in a multiline text box.
        /// </summary>
        public int Rows { get; set; }

        /// <summary>
        /// Gets or sets the type of control rendered in <see cref="FieldAccessMode.ReadOnly"/> access mode.
        /// </summary>
        public BoundTextBox.ReadOnlyModeControl ReadOnlyMode { get; set; }

        #endregion

        #region Methods.

        /// <summary>
        /// Defines the <see cref="DataGrid"/> that child textbox controls and the template belong to.
        /// </summary>
        /// <param name="container">The <b>TableCell</b> which contains the textbox controls instantiated by this template.</param>
        public override void InstantiateIn(Control container)
        {
            BoundTextBox textBox = new BoundTextBox();
            textBox.DataBinding += new EventHandler(this.BindDisplayValue);
            if (this.SkinID != null)
            {
                textBox.SkinID = this.SkinID;
                Page page = HttpContext.Current.Handler as Page;
                if (page != null)
                    textBox.ApplyStyleSheetSkin(page);
            }

            container.Controls.Add(textBox);
        }

        private void BindDisplayValue(object sender, EventArgs e)
        {
            BoundTextBox textBox = (BoundTextBox)sender;
            ApplyStyle(textBox);
            if (this.MaxLength > 0)
                textBox.MaxLength = this.MaxLength;
            if (this.AllowedChars != null && this.AllowedChars.Length > 0)
                textBox.AllowedChars = this.AllowedChars;
            textBox.TextMode = this.TextMode;
            textBox.Rows = this.Rows;
            textBox.ReadOnlyMode = this.ReadOnlyMode;

            DataGridItem currentItem = (DataGridItem)textBox.NamingContainer;
            object val = DataBinder.Eval(currentItem.DataItem, this.BoundField.BindingName);
            object displayValue = (this.BoundField.CodeList == null) ? val : this.BoundField.CodeList.GetDisplayValue(val);
            textBox.Text = this.Formatter.Format(displayValue);

            bool isReadOnly = ConfigureAccessMode(textBox);
            if (isReadOnly)
            {
                // Default is white which hides the grid's color (eg. when item is selected).
                textBox.BackColor = Color.Transparent;
                textBox.Style["cursor"] = "pointer";
            }
        }

        #endregion
    }
}